home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / netz / amislate / slaterexx / chess.rexx next >
OS/2 REXX Batch file  |  1995-08-05  |  39KB  |  1,269 lines

  1. /* Chess for AmiSlate v1.0! */
  2. /* This program should be run on a screen with at least 8 colors */
  3.  
  4. /* Constants for use with AmiSlate's ARexx interface */
  5. AMode.DOT      =  0 
  6. AMode.PEN      =  1 
  7. AMode.LINE     =  2 
  8. AMode.CIRCLE   =  3 
  9. AMode.SQUARE   =  4 
  10. AMode.POLY     =  5 
  11. AMode.FLOOD    =  6 
  12. AMode.DTEXT    =  7 
  13.  
  14. AMessage.TIMEOUT     = 1    /* No events occurred in specified time period */
  15. AMessage.MESSAGE     = 2    /* Message recieved from remote Amiga */
  16. AMessage.MOUSEDOWN   = 4    /* Left mouse button press in drawing area */
  17. AMessage.MOUSEUP     = 8    /* Left mouse button release in drawing area */
  18. AMessage.RESIZE      = 16    /* Window was resized--time to redraw screen? */ 
  19. AMessage.QUIT        = 32    /* AmiSlate is shutting down */
  20. AMessage.CONNECT     = 64    /* Connection established */
  21. AMessage.DISCONNECT  = 128    /* Connection broken */
  22. AMessage.TOOLSELECT  = 256    /* Tool Selected */
  23. AMessage.COLORSELECT = 512    /* Palette Color selected */
  24. AMessage.KEYPRESS    = 1024    /* Key pressed */
  25. AMessage.MOUSEMOVE   = 2048     /* Mouse was moved */
  26.  
  27. ACTIVE  = 1
  28. PASSIVE = 0
  29.  
  30. /* Chess specific constants */
  31. GlobData.HILITEPEN = 2
  32. GlobData.SQUAREPEN1 = 3        /* It would probably be better to get these */
  33. GlobData.SQUAREPEN2 = 4        /* dynamically, wouldn't it? */
  34. GlobData.SIDE1PEN   = 2
  35. GlobData.SIDE2PEN   = 1
  36. GlobData.moverr = "No error"
  37.  
  38. piece.BLANK  = 0
  39. piece.PAWN   = 1
  40. piece.ROOK   = 2
  41. piece.KNIGHT = 4
  42. piece.BISHOP = 8
  43. piece.QUEEN  = 16
  44. piece.KING   = 32
  45.  
  46. /* Defaults */
  47. BInitialSquareSet = 0
  48.  
  49. /* Get our host's name--always given as first argument when run from Amislate */
  50. parse arg CommandPort ActiveString
  51.  
  52. if (length(CommandPort) == 0) then do
  53.     say ""
  54.     say "Usage:  rx chess.rexx <REXXPORTNAME>"
  55.     say "        (REXXPORTNAME is usually AMISLATE)"
  56.     say ""
  57.     say "Or run from the Rexx menu within AmiSlate."
  58.     say ""
  59.     exit 0
  60.     end
  61.     
  62. /* Send all commands to this host */
  63. address (CommandPort) 
  64. options results
  65.  
  66. /* Reserves pixels for a future toolbar -- currently, none */
  67. GlobData.ToolBarHeight = 0
  68.  
  69. /* Check to see which tool is selected, whether we are connected */
  70. GlobData.BFlood = 0
  71. GetStateAttrs stem stateattrs.
  72.  
  73. if (stateattrs.mode > 1) then GlobData.BFlood = 1
  74.  
  75. /* Parse command line argument to see if we've been activated by 
  76.    a remote request or a local user */
  77. check = upper(left(ActiveString,3))
  78. if (upper(left(ActiveString,3)) ~= 'RE') then 
  79.     do
  80.         GlobData.BActive = 1
  81.     end
  82.     else
  83.     do    
  84.         GlobData.BActive = 0
  85.     end
  86.  
  87. /* See if we're connected */
  88. GetRemoteStateAttrs stem rstateattrs.
  89.  
  90. if (rstateattrs.mode > -1) then 
  91.     do
  92.         GlobData.BConnectMode = 1
  93.     end
  94.     else
  95.     do
  96.         GlobData.BConnectMode = 0
  97.     end
  98.     
  99. 'lock on'            /* keep user from drawing */
  100. 'lockpalette on'        /* match colors, if possible */
  101.  
  102. success = InitChessArray()
  103.  
  104. /* Initiator goes first */
  105. GlobData.turn = ACTIVE
  106.  
  107.  
  108. /* Handshaking for two-computer game */
  109. if (GlobData.BConnectMode = 1) then 
  110. do
  111.     if (GlobData.BActive == 1) then 
  112.     do
  113.         SetWindowTitle '"'||"Requesting game from remote user"||'"' 
  114.     RemoteRexxCommand '"'||"Would you like to play chess?"||'"' "slaterexx:chess.rexx"
  115.     
  116.         waitevent stem handshake. MESSAGE
  117.         if (handshake.message == 0) then 
  118.         do
  119.             SetWindowTitle '"'||"Chess Game Refused"||'"'
  120.             exit
  121.         end
  122.     success = DrawChessBoard()
  123.     SetRemoteWindowTitle '"'||"Their turn (White)"||'"'
  124.     end
  125.     else
  126.     do
  127.         /* Examine window to get dimensions */
  128.     GetWindowAttrs stem winattrs.
  129.        GlobData.BoardWidth = winattrs.width  - 58
  130.        GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  131.     end
  132. end
  133. else 
  134. do
  135.     success = DrawChessBoard()
  136. end        
  137.  
  138. /* If we're in line mode, tell the remote client */
  139. if (GlobData.BActive == 1) then sendmessage "*****"||GlobData.BFlood
  140.  
  141.  
  142.  
  143. success = UpdateStatus()
  144. do while(1)
  145.     waitevent stem event. RESIZE MOUSEDOWN MOUSEUP TOOLSELECT MESSAGE DISCONNECT
  146.     
  147.     if (event.type == AMessage.DISCONNECT) then GlobData.BConnectMode = 0
  148.     if (event.type == AMessage.QUIT) then exit
  149.     if (event.type == AMessage.RESIZE) then do
  150.         if ((GlobData.BActive == 1)|(GlobData.BConnectMode == 0)) then do
  151.            success = DrawChessBoard()
  152.         end
  153.         else do
  154.            /* Just examine window to get new dimensions */
  155.            GetWindowAttrs stem winattrs.
  156.            GlobData.BoardWidth = winattrs.width  - 58
  157.            GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  158.         end
  159.              success = UpdateStatus()
  160.     end
  161.  
  162.     if (event.type == AMessage.MESSAGE) then do
  163.         success = ParseMove(event.message)
  164.         if (success == 1) then do
  165.              GlobData.turn = GlobData.BActive
  166.              success = UpdateStatus()
  167.              end
  168.         end
  169.         
  170.     if ((event.type = AMessage.TOOLSELECT)&(GlobData.BActive == 1)) then do
  171.         BOldFlood = GlobData.BFlood
  172.         if (event.code1 < 1) then GlobData.BFlood = 0
  173.         if (event.code1 >= 1) then GlobData.BFlood = 1
  174.         if ((event.code1 = 7)|(GlobData.BFlood ~= BOldFlood)) then do
  175.             success = DrawChessBoard()
  176.             sendmessage "*****"||GlobData.BFlood
  177.             end
  178.         end
  179.  
  180.     if (((event.type = AMessage.MOUSEDOWN)|((event.type = AMessage.MOUSEUP)&(BInitialSquareSet = 1)))&((GlobData.turn = GlobData.BActive)|(GlobData.BConnectMode = 0))) then do
  181.         xtemp = event.x
  182.         SelectChessSquareX = -1
  183.         do while (xtemp > 0)
  184.             xtemp = xtemp - trunc(GlobData.BoardWidth / 8)
  185.             SelectChessSquareX = SelectChessSquareX + 1
  186.             end
  187.         ytemp = event.y
  188.         SelectChessSquareY = -1
  189.         do while (ytemp > GlobData.ToolBarHeight)
  190.             ytemp = ytemp - trunc(GlobData.BoardHeight / 8)
  191.             SelectChessSquareY = SelectChessSquareY + 1
  192.             end
  193.  
  194.         ThisSquare = ChessBoard.SelectChessSquareX.SelectChessSquareY        
  195.         if (((GlobData.turn == ACTIVE)&(ThisSquare > 0))|((GlobData.turn == PASSIVE)&(ThisSquare < 0))|(BInitialSquareSet == 1)) then do
  196.    
  197.                /* HiLite selected square */
  198.             success = SelectChessSquare(SelectChessSquareX, SelectChessSquareY, GlobData.HILITEPEN)
  199.     
  200.              if (BInitialSquareSet = 0) then do
  201.                 BInitialSquareSet = 1
  202.                 SelectedSquareX = SelectChessSquareX
  203.                 SelectedSquareY = SelectChessSquareY
  204.                 end
  205.             else do
  206.                 /* De-HiLite old square */
  207.                 sqc = SquareColor(SelectedSquareX, SelectedSquareY)
  208.                 success = SelectChessSquare(SelectedSquareX, SelectedSquareY, sqc)
  209.             
  210.                 /* De-HiLite this square--move done! */    
  211.                 sqc = SquareColor(SelectChessSquareX, SelectChessSquareY)
  212.                 success = SelectChessSquare(SelectChessSquareX,SelectChessSquareY, sqc)
  213.     
  214.                 BInitialSquareSet = 0
  215.  
  216.             GlobData.moverr = "No error"
  217.  
  218.             moveResult = MovePiece(SelectedSquareX, SelectedSquareY, SelectChessSquareX, SelectChessSquareY)
  219.             if (moveResult > 0) then do
  220.                     szSendString = "1" || selectedSquareX || SelectedSquareY || SelectChessSquareX || SelectChessSquareY || moveResult
  221.                     sendmessage szSendString
  222.                     if (GlobData.turn == 1) then do
  223.                         GlobData.turn = 0
  224.                         end
  225.                     else do
  226.                         GlobData.turn = 1
  227.                         end
  228.                     success = UpdateStatus()
  229.                     end
  230.                 else do
  231.                     SetWindowTitle '"'||"Error: "|| GlobData.moverr || '"'
  232.                     DisplayBeep
  233.                     end
  234.                 end
  235.             end
  236.         end
  237.     end
  238. exit
  239.  
  240.  
  241.  
  242. /* --------------------------------------------------------------- */
  243. /* procedure MovePiece                           */
  244. /* --------------------------------------------------------------- */
  245. MovePiece: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  246.     parse arg OldX, OldY, X, Y
  247.     
  248.     if (CheckMove(OldX, OldY, X, Y, 1) == 0) then do
  249.         return 0    
  250.         end
  251.         
  252.     /* Special case for castling--king moves to earlier square */
  253.     if (abs(ChessBoard.OldX.OldY) == Piece.King) then do
  254.         if ((OldX == 3)&(X == 0)) then X = 1
  255.         if ((OldX == 3)&(X == 7)) then X = 6
  256.         end
  257.                 
  258.     if (UpdatePiecePos(OldX, OldY, X, Y) == 0) then do
  259.         EasyRequest Chess_Error "555:UPP_failed" Okay
  260.         return 0
  261.         end    
  262.     
  263.     /* Was there a death here?  If so, remove dying piece */
  264.     if (ChessBoard.X.Y ~= Piece.BLANK) then do
  265.         VictimPiece = GetPiecePos(X, Y)
  266.         if (VictimPiece > 0) then do
  267.             PiecePosX.1.VictimPiece = 9999
  268.             PiecePosY.1.VictimPiece = 9999
  269.             end
  270.         else do
  271.             VictimPiece = abs(VictimPiece)
  272.             PiecePosX.2.VictimPiece = 9999
  273.             PiecePosY.2.VictimPiece = 9999
  274.             end
  275.         end
  276.  
  277.     returnresult = 1
  278.     
  279.     /* Check for pawn promotion */
  280.     if (((Y == 7)&(ChessBoard.OldX.OldY == Piece.PAWN))|((Y == 0)&(ChessBoard.OldX.OldY == -Piece.PAWN))) then do
  281.             if (ChessBoard.OldX.OldY = Piece.PAWN) then do
  282.                 tSide = 1
  283.                 end
  284.             else do
  285.                 tSide = -1
  286.             end
  287.             
  288.             EasyRequest '"'||"Your pawn is getting a promotion!"||'"' '"'||"What do you want to promote your pawn to?"||'"' "Queen|Rook|Bishop|Knight"
  289.         if (rc == 0) then ChessBoard.OldX.OldY = tSide * Piece.Knight
  290.         if (rc == 1) then ChessBoard.OldX.OldY = tSide * Piece.Queen
  291.         if (rc == 2) then ChessBoard.OldX.OldY = tSide * Piece.Rook
  292.         if (rc == 3) then ChessBoard.OldX.OldY = tSide * Piece.Bishop
  293.         returnresult = rc + 2    /* For transmission */
  294.     end
  295.     
  296.     ChessBoard.X.Y = ChessBoard.OldX.OldY              /* Then put the piece in the new spot! */
  297.     ChessBoard.OldX.OldY = Piece.BLANK
  298.     
  299.     success=DrawPiece(OldX, OldY, ChessBoard.OldX.OldY, GlobData.BFlood)
  300.     success=DrawPiece(X, Y, ChessBoard.X.Y, GlobData.BFlood)
  301.                     
  302.     return returnresult
  303.  
  304.  
  305. /* --------------------------------------------------------------- */
  306. /* procedure MoveCreatesCheck                           */
  307. /*                                   */
  308. /* This procedure will determine if the move (OldX,OldY)->(X,Y)    */
  309. /* will get the piece at CheckX, CheckY into danger (i.e. check    */
  310. /* for a king, etc. ) without affecting the board              */
  311. /* --------------------------------------------------------------- */
  312. MoveCreatesCheck: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. 
  313.     parse arg OldX, OldY, X, Y, CheckX, CheckY
  314.     
  315.     if (ChessBoard.OldX.OldY == Piece.BLANK) then do
  316.         EasyRequest Chess_Error "MoveCreatesCheck:_Bad_Attacker!" Okay
  317.         return 1
  318.         end
  319.     
  320.     AttackerPiece = ChessBoard.OldX.OldY
  321.     AttackerID = GetPiecePos(OldX, OldY)
  322.     if (AttackerID == 0) then do
  323.         EasyRequest Chess_Error "MoveCreatesCheck:_Anonymous_Attacker!" Okay
  324.         return 1
  325.         end
  326.     if (AttackerID < 0) then do
  327.         AttackerID = abs(AttackerID)
  328.         nAttackerSide = 2
  329.         end
  330.     else do
  331.         nAttackerSide = 1
  332.         end
  333.             
  334.     TargetPiece = ChessBoard.X.Y
  335.     TargetID    = 0            /* Default = unset/error */    
  336.     if (TargetPiece ~= Piece.BLANK) then do
  337.     TargetID = GetPiecePos(X,Y)
  338.     if (TargetID == 0) then do
  339.         EasyRequest Chess_Error "MoveCreatesCheck:_Anonymous_defender!" Okay
  340.         return 1
  341.         end
  342.     if (TargetID < 0) then do
  343.         TargetID = abs(TargetID)
  344.         nTargetSide = 2
  345.         end
  346.     else do
  347.         nTargetSide = 1
  348.         end
  349.     PiecePosX.nTargetSide.TargetID = 9999
  350.     PiecePosY.nTargetSide.TargetID = 9999
  351.     end
  352.  
  353.     /* Move the attacker, on both arrays */
  354.         PiecePosX.nAttackerSide.AttackerID = X
  355.         PiecePosY.nAttackerSide.AttackerID = Y
  356.     ChessBoard.X.Y = AttackerPiece              /* Then put the piece in the new spot! */
  357.  
  358.     /* Erase the attacker from his old position */
  359.     ChessBoard.OldX.OldY = Piece.BLANK
  360.  
  361.     /* Now see if we have a check situation */
  362.     returnFlag = IsInCheck(CheckX,CheckY)
  363.     
  364.     /* Clean up from our little sim -- move piece back and replace victim */
  365.     ChessBoard.OldX.OldY = AttackerPiece
  366.     PiecePosX.nAttackerSide.AttackerID = OldX
  367.     PiecePosY.nAttackerSide.AttackerID = OldY
  368.     
  369.     ChessBoard.X.Y = TargetPiece
  370.     if (TargetID ~= 0) then do
  371.         PiecePosX.nTargetSide.TargetID = X
  372.         PiecePosY.nTargetSide.TargetID = Y
  373.         end
  374.     
  375.     return ReturnFlag
  376.     
  377.  
  378.     
  379. /* --------------------------------------------------------------- */
  380. /* procedure UpdatePiecePos                               */
  381. /* --------------------------------------------------------------- */
  382. UpdatePiecePos: procedure expose ChessBoard. PiecePosX. PiecePosY.
  383.     parse arg OldX, OldY, X, Y
  384.     
  385.     ThisPiece = GetPiecePos(OldX, OldY)
  386.     
  387.     if (ThisPiece == 0) then do
  388.         EasyRequest Chess_Error "UpdatePiecePos:update_empty_square?_huh?" Okay
  389.         return 0
  390.         end
  391.         
  392.     if (ThisPiece > 0) then do
  393.         PiecePosX.1.ThisPiece = X
  394.         PiecePosY.1.ThisPiece = Y
  395.         return 1
  396.         end
  397.     else do
  398.         ThisPiece = abs(ThisPiece)
  399.         PiecePosX.2.ThisPiece = X
  400.         PiecePosY.2.ThisPiece = Y
  401.         return 1
  402.         end
  403.     
  404.     EasyRequest Chess_Error "UpdatePiecePos_error-not_found" Okay
  405.     return 0
  406.  
  407.  
  408.  
  409.  
  410. /* --------------------------------------------------------------- */
  411. /* procedure GetPiecePos                              */
  412. /*                                   */
  413. /* Given a set of co-ordinates, this function returns the PiecePos */
  414. /* index/ID of the piece there.  Positive values is for Side1 (top */
  415. /* and negative values are for side2 (bottom).  0 = blank/error.   */
  416. /* --------------------------------------------------------------- */
  417. GetPiecePos: procedure expose PiecePosX. PiecePosY. ChessBoard.
  418.     parse arg X, Y
  419.     
  420.     if ((ChessBoard.X.Y == 0)|(X < 0)|(X > 7)|(Y < 0)|(Y > 7)) then return 0
  421.         
  422.     if (ChessBoard.X.Y > 0) then do
  423.         pi = 1
  424.         do while (pi < 17)
  425.             if ((PiecePosX.1.pi == X)&(PiecePosY.1.pi == Y)) then do
  426.                 return pi
  427.                 end
  428.             pi = pi + 1
  429.             end
  430.         end
  431.     else do
  432.         pi = 1
  433.         do while (pi < 17)
  434.             if ((PiecePosX.2.pi == X)&(PiecePosY.2.pi == Y)) then do
  435.                 return -pi
  436.                 end
  437.             pi = pi + 1
  438.             end
  439.         end
  440.     return 0
  441.  
  442.  
  443. /* --------------------------------------------------------------- */
  444. /* procedure InternalMove                          */
  445. /*                                   */
  446. /* Updates all necessary piece movement vars in memory only        */
  447. /*                                   */
  448. /* --------------------------------------------------------------- */
  449. InternalMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY.
  450.     parse arg XFrom, YFrom, XTo, YTo
  451.  
  452.     if (UpdatePiecePos(XFrom, YFrom, XTo, YTo) == 0) then do
  453.         EasyRequest Chess_Error "997:UPP_failed" Okay
  454.         return 0
  455.         end    
  456.     ChessBoard.XTo.YTo = ChessBoard.XFrom.YFrom
  457.     ChessBoard.XFrom.YFrom = Piece.BLANK
  458.     return 1
  459.  
  460.  
  461.  
  462. /* --------------------------------------------------------------- */
  463. /* procedure CastleOkay                          */
  464. /*                                   */
  465. /* returns 1 if the castling move is okay, else zero                */
  466. /*                                   */
  467. /* --------------------------------------------------------------- */
  468. CastleOkay: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  469.     parse arg XFrom, YFrom, XTo, YTo
  470.  
  471.     GlobData.moverr = "Can't castle from there"
  472.  
  473.     /* Only can castle from King's starting position */
  474.     if (XFrom != 3) then do
  475.         GlobData.moverr = "Can't castle after king has moved"
  476.         return 0
  477.         end
  478.         
  479.     if (YFrom != YTo) then return 0
  480.         
  481.     /* First thing: determine what side we're on */
  482.     if (ChessBoard.XFrom.YFrom < 0) then do
  483.         SideToCheck = 2
  484.         if (YFrom != 7) then return 0
  485.         end
  486.     else do
  487.         SideToCheck = 1
  488.         if (YFrom != 0) then return 0
  489.         end
  490.         
  491.     /* can't castle if king has already moved */
  492.     if (ChessBoard.KingMoved.SideToCheck == 1) then do
  493.         GlobData.moverr = "Can't castle after king has moved"
  494.         return 0
  495.         end
  496.     
  497.     LeftOrRight = 0            /* Default = error */
  498.     if (XTo == 0) then do
  499.         LeftOrRight = 1        /* Left */
  500.         NewRookX = 2
  501.         NewKingX = 1
  502.         /* Can't castle if rook has moved */
  503.         if (ChessBoard.LeftRookMoved.SideToCheck == 1) then do
  504.             GlobData.moverr = "Can't castle after rook has moved"
  505.             return 0
  506.             end
  507.         end
  508.     if (XTo == 7) then do
  509.         LeftOrRight = 2     /* Right */
  510.         NewRookX = 5
  511.         NewKingX = 6
  512.         /* Can't castle if rook has moved */
  513.         if (ChessBoard.RightRookMoved.SideToCheck == 1) then do
  514.             GlobData.moverr = "Can't castle after rook has moved"
  515.             return 0
  516.             end
  517.         end        
  518.     if (LeftOrRight == 0) then do
  519.         GlobData.moverr = "You should never see this error"
  520.         return 0    /* This should never happen */
  521.         end    
  522.     
  523.     /* Make sure all spaces between king and rook are clear */
  524.     if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  525.         GlobData.moverr = "There are pieces between king and rook"
  526.         return 0
  527.         end
  528.         
  529.     /* Can't castle out of check */
  530.     if (IsInCheck(XFrom,YFrom) == 1) then do
  531.         GlobData.moverr = "Can't castle out of check"
  532.         return 0
  533.         end
  534.     
  535.     /* Move rook to new position, in my head anyway */
  536.     if (InternalMove(XTo, YTo, newRookX, YTo) == 0) then return 0
  537.     
  538.     /* Move king to new position, in my head anyway */
  539.     if (InternalMove(XFrom, YFrom, newKingX, YFrom) == 0) then return 0
  540.  
  541.     /* See if this causes check */
  542.     if (IsInCheck(newKingX,YFrom) == 1) then do
  543.         /* oops, would be a move into check.  No can do! */
  544.         /* So move everything back! */
  545.  
  546.         /* Move rook back to old position, in my head anyway */
  547.         if (InternalMove(newRookX, YTo, XTo, YTo) == 0) then return 0
  548.         
  549.         /* Move king back to old position, in my head anyway */
  550.         if (InternalMove(newKingX, YFrom, XFrom, YFrom) == 0) then return 0
  551.  
  552.         GlobData.moverr = "Can't castle into check"
  553.         
  554.         /* and fail */
  555.         return 0
  556.         end
  557.         
  558.     /* If we're here, then the castle is acceptable.  Put the king
  559.        back for now--it'll be moved by the normal turn--but we'll 
  560.        move the rook ourselves! */
  561.     
  562.     /* Move king back to old position, in my head anyway */
  563.     if (InternalMove(newKingX, YFrom, XFrom, YFrom) == 0) then return 0
  564.     
  565.     /* Display and transmit the rook's move */
  566.     
  567.     /* Erase old rook */
  568.     success = DrawPiece(XTo, YTo, ChessBoard.XTo.YTo, GlobData.BFlood)
  569.     
  570.     /* Draw new rook */
  571.     success = DrawPiece(newRookX, YTo, ChessBoard.newRookX.YTo, GlobData.BFlood)
  572.     
  573.     /* Transmit move -- 2 means don't lose turn yet */
  574.     szSendString = "2" || XTo || YTo || newRookX || YTo || "0"
  575.         sendmessage szSendString
  576.  
  577.     return 1
  578.     
  579.  
  580. /* --------------------------------------------------------------- */
  581. /* procedure CheckMove                          */
  582. /* --------------------------------------------------------------- */
  583. CheckMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  584.     parse arg XFrom, YFrom, XTo, YTo, BCheckForCheck
  585.     
  586.     /* A move off of the board is illegal */
  587.     if ((XTo < 0)|(XTo > 7)|(YTo < 0)|(YTo > 7)) then do
  588.         GlobData.moverr = "Can't move off of board"
  589.         return 0
  590.         end
  591.         
  592.     /* A move from off of the board is illegal */
  593.     if ((XFrom < 0)|(XFrom > 7)|(YFrom < 0)|(YFrom > 7)) then do
  594.         GlobData.moverr = "Can't move from off of board"
  595.         return 0
  596.         end
  597.         
  598.     /* Blanks can't move */
  599.     if (ChessBoard.XFrom.YFrom == Piece.BLANK) then do
  600.         GlobData.moverr = "Can't move a blank square"
  601.         return 0
  602.         end
  603.  
  604.     
  605.     /* A move to the same spot we're on is illegal */
  606.     if ((XFrom == XTo)&(YFrom == YTo)) then do
  607.         GlobData.moverr = "Can't move onto yourself"
  608.         return 0
  609.         end
  610.  
  611.     /* A move onto one of your own pieces is illegal */
  612.     if ((ChessBoard.XTo.YTo * ChessBoard.XFrom.YFrom) > 0) then do
  613.         /* except when you're castling */
  614.         if (((ChessBoard.XTo.YTo == Piece.Rook)&(ChessBoard.XFrom.YFrom == Piece.King))|((ChessBoard.XTo.YTo == -Piece.Rook)&(ChessBoard.XFrom.YFrom == -Piece.King))) then do
  615.              /* nothing right now, we'll check for castling later */
  616.              end 
  617.         else do
  618.              GlobData.moverr = "Can't attack your own piece"
  619.              return 0
  620.              end
  621.     end
  622.     
  623.     /* Rules for the PAWN */    
  624.     if (abs(ChessBoard.XFrom.YFrom) == Piece.PAWN) then do
  625.         GlobData.moverr = "Bad pawn move"
  626.         if (ChessBoard.XFrom.YFrom < 0) then do
  627.             PawnMoveDir = -1 
  628.             end
  629.             else PawnMoveDir = 1
  630.         if ((XTo == XFrom)&(ChessBoard.XTo.YTo ~= Piece.BLANK)) then do
  631.             GlobData.moverr = "Pawn can't attack forward"
  632.              return 0
  633.              end
  634.         if ((XTo == XFrom)&(abs(YFrom - YTo) == 2)) then do
  635.             /* First move for a pawn can be two spaces, if both spaces are blank */
  636.             Ytemp = YFrom+PawnMoveDir
  637.             if ((ChessBoard.XFrom.Ytemp) ~= Piece.BLANK) then return 0
  638.             if ((YFrom == 1)&(PawnMoveDir ~= 1)) then return 0
  639.             if ((YFrom == 6)&(PawnMoveDir ~= -1)) then return 0
  640.             if ((YFrom ~= 1)&(YFrom ~= 6)) then return 0
  641.             end
  642.         else do
  643.             if (YTo ~= (YFrom + PawnMoveDir)) then return 0
  644.             if (abs(XFrom - XTo) > 1) then return 0
  645.             if ((abs(XFrom - XTo) == 1)&(ChessBoard.XTo.YTo == Piece.BLANK)) then return 0    
  646.             end
  647.         end 
  648.     
  649.     /* Rules for the ROOK */
  650.     if (abs(ChessBoard.XFrom.YFrom) == Piece.ROOK) then do
  651.         if ((XFrom ~= XTo)&(YFrom ~= YTo)) then do
  652.             GlobData.moverr = "Rook must move horizontally or vertically"
  653.             return 0
  654.             end
  655.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  656.             GlobData.moverr = "Move is blocked"
  657.             return 0
  658.             end
  659.         end
  660.         
  661.     /* Rules for the KNIGHT */
  662.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KNIGHT) then do
  663.         GlobData.moverr = "Bad knight move"
  664.         if (((abs(XFrom - XTo) ~= 2)|(abs(YFrom - YTo) ~= 1))&((abs(XFrom - XTo) ~= 1)|(abs(YFrom - YTo) ~= 2))) then return 0
  665.         end
  666.         
  667.     /* Rules for the BISHOP */
  668.     if (abs(ChessBoard.XFrom.YFrom) == Piece.BISHOP) then do
  669.         if (abs(XFrom - XTo) ~= abs(YFrom - YTo)) then do
  670.             GlobData.moverr = "Bishop must move diagonally"
  671.             return 0
  672.             end
  673.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  674.             GlobData.moverr = "Move is blocked"
  675.             return 0
  676.             end
  677.         end
  678.  
  679.     /* Rules for the QUEEN */
  680.     if (abs(ChessBoard.XFrom.YFrom) == Piece.QUEEN) then do
  681.         if ((abs(XFrom - XTo) ~= abs(YFrom - YTo))&((XFrom ~= XTo)&(YFrom ~= YTo))) then do
  682.             GlobData.moverr = "Queen must move in a straight line"
  683.             return 0
  684.             end
  685.         if (GlideOK(XFrom,YFrom,XTo,YTo) == 0) then do
  686.             GlobData.moverr = "Move is blocked"
  687.             return 0
  688.             end
  689.         end
  690.  
  691.     /* Rules for the KING */
  692.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  693.         if (((ChessBoard.XTo.YTo == Piece.ROOK)&(ChessBoard.XFrom.YFrom == Piece.KING))|((ChessBoard.XTo.YTo == -Piece.ROOK)&(ChessBoard.XFrom.YFrom == -Piece.KING)))
  694.            then do
  695.                 if (CastleOkay(XFrom,YFrom,XTo,YTo) == 0) then return 0
  696.                 end
  697.            else do
  698.             if ((abs(XTo - XFrom) > 1)|(abs(YTo - YFrom) > 1)) then do
  699.                 GlobData.moverr = "King can only move 1 square"
  700.                 return 0
  701.                 end
  702.            end
  703.     end
  704.     
  705.     if (BCheckForCheck == 0) then return 1
  706.     
  707.     /* Get king's co-ordinates */
  708.     if (Chessboard.XFrom.YFrom > 0) then do
  709.         KingPosX = PiecePosX.1.1
  710.         KingPosY = PiecePosY.1.1        
  711.         end
  712.     else do
  713.         KingPosX = PiecePosX.2.1
  714.         KingPosY = PiecePosY.2.1
  715.         end
  716.  
  717.     /* If king is moving, check were he WILL be, not where he IS */
  718.     if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  719.         KingPosX = XTo
  720.         KingPosY = YTo
  721.         end
  722.         
  723.     if (MoveCreatesCheck(XFrom, YFrom, XTo, YTo, KingPosX, KingPosY) == 1) then do
  724.         if (abs(ChessBoard.XFrom.YFrom) == Piece.KING) then do
  725.                 GlobData.moverr = "Move would put you in check"
  726.             end
  727.             else do
  728.                 GlobData.moverr = "Move does not remove you from check"
  729.             end
  730.         return 0
  731.         end
  732.             
  733.     /* If we passed all these tests, we're ok */        
  734.  
  735.     /* If it's a rook or a king, set the appropriate moved flag */
  736.     if (ChessBoard.XFrom.YFrom == Piece.King) then ChessBoard.KingMoved.1 = 1
  737.     if (ChessBoard.XFrom.YFrom == -Piece.King) then ChessBoard.KingMoved.2 = 1
  738.     
  739.     if (ChessBoard.XFrom.YFrom == Piece.Rook) then do
  740.         if ((XFrom == 0)&(YFrom == 0)) then ChessBoard.LeftRookMoved.1 = 1
  741.         if ((XFrom == 7)&(YFrom == 0)) then ChessBoard.RightRookMoved.1 = 1
  742.         end
  743.     if (ChessBoard.XFrom.YFrom == -Piece.Rook) then do
  744.         if ((XFrom == 0)&(YFrom == 7)) then ChessBoard.LeftRookMoved.2 = 1
  745.         if ((XFrom == 7)&(YFrom == 7)) then ChessBoard.RightRookMoved.2 = 1
  746.         end
  747.                     
  748.     return 1
  749.     
  750.     
  751.     
  752. /* --------------------------------------------------------------- */
  753. /* procedure GlideOK                              */
  754. /* --------------------------------------------------------------- */
  755. GlideOK:    procedure expose ChessBoard. piece.
  756.     parse arg XFrom, YFrom, XTo, YTo
  757.     
  758.     xd = 0
  759.     yd = 0
  760.         
  761.     if ((XTo - XFrom) > 0) then xd = 1
  762.     if ((XTo - XFrom) < 0) then xd = -1
  763.     if ((YTo - YFrom) > 0) then yd = 1
  764.     if ((YTo - YFrom) < 0) then yd = -1
  765.  
  766.     x = XFrom + xd    /* Start scanning after where piece already is */
  767.     y = YFrom + yd
  768.     
  769.     xgoal = XTo 
  770.     ygoal = YTo 
  771.     
  772.     do while ((x ~= xgoal)|(y ~= ygoal))
  773.         if (ChessBoard.x.y ~= Piece.BLANK) then return 0
  774.         if ((x<0)|(y<0)|(x>7)|(y>7)) then do
  775.             EasyRequest Chess_Error "Glide_error!" Okay
  776.             return 0
  777.             end
  778.         x = x + xd
  779.         y = y + yd
  780.         end
  781.         
  782.     return 1
  783.     
  784.  
  785. /* --------------------------------------------------------------- */
  786. /* procedure IsInCheck                           */
  787. /*                                    */
  788. /* returns 1 if the given square is in danger, otherwise 0         */
  789. /* --------------------------------------------------------------- */
  790. IsInCheck: procedure expose ChessBoard. PiecePosX. PiecePosY. piece.
  791.     parse arg X, Y
  792.         
  793.     
  794.     if (ChessBoard.X.Y == 0) then do
  795.         EasyRequest Chess_Error "IsInCheck_:_Square_is_empty!" Okay
  796.         return 0
  797.         end
  798.         
  799.     if (ChessBoard.X.Y > 0) then SideToCheck = 2
  800.     if (ChessBoard.X.Y < 0) then SideToCheck = 1
  801.     
  802.     pi = 1
  803.     do while (pi < 17)
  804.         if (CheckMove(PiecePosX.SideToCheck.pi,PiecePosY.SideToCheck.pi,X,Y,0) == 1) then return 1
  805.         pi = pi + 1
  806.     end
  807.     return 0
  808.  
  809.  
  810.  
  811. /* --------------------------------------------------------------- */
  812. /* procedure                                */
  813. /* --------------------------------------------------------------- */
  814. InitChessArray: procedure expose ChessBoard. piece. PiecePosX. PiecePosY.
  815.  
  816.    /* Set special castling info for both sides */
  817.    ChessBoard.KingMoved.1 = 0
  818.    ChessBoard.KingMoved.2 = 0
  819.    ChessBoard.LeftRookMoved.1  = 0
  820.    ChessBoard.RightRookMoved.1 = 0
  821.    ChessBoard.LeftRookMoved.2  = 0
  822.    ChessBoard.RightRookMoved.2 = 0
  823.    
  824.    /* Set Kings */
  825.    ChessBoard.3.0 = Piece.KING
  826.    ChessBoard.3.7 = -Piece.KING
  827.  
  828.    /* Set king position markers */
  829.    PiecePosX.1.1 = 3
  830.    PiecePosY.1.1 = 0
  831.    PiecePosX.2.1 = 3
  832.    PiecePosY.2.1 = 7
  833.  
  834.    /* Set Queens */
  835.    ChessBoard.4.0 = Piece.QUEEN
  836.    ChessBoard.4.7 = -Piece.QUEEN
  837.  
  838.    /* Set queen position markers */
  839.    PiecePosX.1.2 = 4
  840.    PiecePosY.1.2 = 0
  841.    PiecePosX.2.2 = 4
  842.    PiecePosY.2.2 = 7
  843.  
  844.    /* Set rooks */
  845.    ChessBoard.0.0 = Piece.ROOK
  846.    ChessBoard.7.0 = Piece.ROOK
  847.    ChessBoard.0.7 = -Piece.ROOK
  848.    ChessBoard.7.7 = -Piece.ROOK
  849.  
  850.    /* Set rook position markers */
  851.    PiecePosX.1.3 = 0
  852.    PiecePosY.1.3 = 0
  853.    PiecePosX.1.4 = 7
  854.    PiecePosY.1.4 = 0
  855.    
  856.    PiecePosX.2.3 = 0
  857.    PiecePosY.2.3 = 7
  858.    PiecePosX.2.4 = 7
  859.    PiecePosY.2.4 = 7
  860.    
  861.    /* Set knights */
  862.    ChessBoard.1.0 = Piece.KNIGHT
  863.    ChessBoard.6.0 = Piece.KNIGHT
  864.    ChessBoard.1.7 = -Piece.KNIGHT
  865.    ChessBoard.6.7 = -Piece.KNIGHT
  866.  
  867.    /* Set knight position markers */
  868.    PiecePosX.1.5 = 1
  869.    PiecePosY.1.5 = 0
  870.    PiecePosX.1.6 = 6
  871.    PiecePosY.1.6 = 0
  872.    
  873.    PiecePosX.2.5 = 1
  874.    PiecePosY.2.5 = 7
  875.    PiecePosX.2.6 = 6
  876.    PiecePosY.2.6 = 7
  877.  
  878.    /* Set bishops */
  879.    ChessBoard.2.0 = Piece.BISHOP
  880.    ChessBoard.5.0 = Piece.BISHOP
  881.    ChessBoard.2.7 = -Piece.BISHOP
  882.    ChessBoard.5.7 = -Piece.BISHOP
  883.  
  884.    /* Set bishop position markers */
  885.    PiecePosX.1.7 = 2
  886.    PiecePosY.1.7 = 0
  887.    PiecePosX.1.8 = 5
  888.    PiecePosY.1.8 = 0
  889.    
  890.    PiecePosX.2.7 = 2
  891.    PiecePosY.2.7 = 7
  892.    PiecePosX.2.8 = 5
  893.    PiecePosY.2.8 = 7   
  894.  
  895.    /* Set rows of pawns */
  896.    jx = 0
  897.    do while (jx < 8)
  898.        ChessBoard.jx.1 = Piece.PAWN
  899.        ppTemp = jx + 9
  900.        PiecePosX.1.ppTemp = jx
  901.        PiecePosY.1.ppTemp = 1
  902.     jx = jx + 1
  903.        end
  904.    
  905.    jx = 0
  906.    do while (jx < 8)
  907.     ChessBoard.jx.6 = -1        /* - means bottom team */
  908.        ppTemp = jx + 9
  909.        PiecePosX.2.ppTemp = jx
  910.        PiecePosY.2.ppTemp = 6
  911.     jx = jx + 1
  912.     end
  913.   
  914.    /* Center of board is all blanks */
  915.    jy = 2
  916.    do while (jy < 6)
  917.     jx = 0
  918.     do while (jx < 8)
  919.         ChessBoard.jx.jy = Piece.BLANK
  920.         jx = jx + 1
  921.     end
  922.     jy = jy + 1
  923.    end
  924.  
  925.    return 1
  926.  
  927.  
  928.  
  929. /* --------------------------------------------------------------- */
  930. /* procedure DrawChessBoard                       */
  931. /* --------------------------------------------------------------- */
  932. DrawChessBoard: procedure expose ChessBoard. GlobData. piece.
  933.  
  934.    /* Say what we're doing */
  935.    SetWindowTitle '"'||"Drawing Chess Board, Please Wait"||'"'
  936.    SetRemoteWindowTitle '"'||"Drawing Chess Board, Please Wait"||'"'
  937.  
  938.    /* Examine window to get dimensions */
  939.    GetWindowAttrs stem winattrs.
  940.    GlobData.BoardWidth = winattrs.width  - 58
  941.    GlobData.BoardHeight= winattrs.height - 53 - GlobData.ToolBarHeight
  942.    if (winattrs.depth < 2) then do
  943.     EasyRequest Chess_Error '"'||"You need at least a 4-color screen to play chess!"||'"' '"'||"Abort Chess"||'"'
  944.     SetWindowTitle '"'||"Chess game exited."||'"'
  945.     exit 0
  946.     end 
  947.    if (winattrs.depth = 2) then GlobData.SQUAREPEN2 = 0        /* keep it within our palette range! */
  948.  
  949.    /* Clear Screen */
  950.    clear
  951.    jy = 0
  952.    do while (jy < 8)
  953.     jx = 0
  954.     do while (jx < 8)
  955.         success = DrawPiece(jx, jy, ChessBoard.jx.jy, GlobData.BFlood)
  956.         jx = jx + 1
  957.     end
  958.     jy = jy + 1
  959.    end
  960.  
  961.    return 1
  962.     
  963. /* --------------------------------------------------------------- */
  964. /* procedure SquareColor                                              */
  965. /*                                                                      */
  966. /* Given the X,Y co-ordinates (0-7,0-7) of a chess square, return  */
  967. /* its pen color.                                                    */
  968. /* --------------------------------------------------------------- */
  969. SquareColor: procedure expose GlobData.
  970.     parse arg XX, YY
  971.  
  972. if ((XX+ YY)/2) = trunc((XX + YY)/2) then
  973.     return GlobData.SQUAREPEN1
  974. else
  975.     return GlobData.SQUAREPEN2 
  976.  
  977.  
  978. /* --------------------------------------------------------------- */
  979. /* procedure SelectChessSquare                       */
  980. /* --------------------------------------------------------------- */
  981. SelectChessSquare: procedure expose GlobData.
  982.     parse arg ChessSquareSelectX, ChessSquareSelectY, PenToSelectWith
  983.  
  984.    xleft   = trunc(GlobData.BoardWidth / 8) * ChessSquareSelectX
  985.    ytop    = (trunc(GlobData.BoardHeight / 8) * ChessSquareSelectY) + GlobData.ToolBarHeight
  986.    xright  = xleft + trunc(GlobData.BoardWidth / 8)
  987.    ybottom = ytop + trunc(GlobData.BoardHeight / 8)
  988.  
  989.    setfpen PenToSelectWith
  990.    square xleft ytop (xright-1) (ybottom-1)
  991.    return 1
  992.  
  993.  
  994. /* --------------------------------------------------------------- */
  995. /* procedure ParseMove                           */
  996. /* --------------------------------------------------------------- */
  997. ParseMove: procedure expose ChessBoard. piece. PiecePosX. PiecePosY. GlobData.
  998.     parse arg MoveString
  999.     
  1000.    /* parses a move of the form MABCD0 , where 
  1001.        M = checkcode, A = X1, B = Y1, C = X2, D = Y2.  No checking needs to
  1002.        be done on the move, as that will all have been done before allowing
  1003.        it to be sent */   
  1004.     
  1005.    leftpart = left(MoveString,3)
  1006.    rightpart = right(MoveString,3)
  1007.  
  1008.    checkcode = left(leftpart,1)
  1009.    promcode = right(rightpart,1)
  1010.  
  1011.    /* Special case:  If the message is of the form *****N, then N is
  1012.       the new value for BFlood */
  1013.    if (checkcode == '*') then do
  1014.        GlobData.BFlood = promcode
  1015.        return 2    /* means stick around for another move */
  1016.        end
  1017.        
  1018.    /* If its my turn, then he don't get to move! */
  1019.    if (GlobData.turn == GlobData.BActive) then return 0
  1020.  
  1021.    leftpart = right(leftpart,2)
  1022.    rightpart = left(rightpart,2)
  1023.    
  1024.    mx1 = left(leftpart,1)
  1025.    my1 = right(leftpart,1)
  1026.    mx2 = left(rightpart,1)
  1027.    my2 = right(rightpart,1)
  1028.    
  1029.    if (UpdatePiecePos(mx1, my1, mx2, my2) == 0) then do
  1030.        EasyRequeset Chess_Error "555:_UPP_failed" Okay
  1031.        return 0
  1032.        end    
  1033.  
  1034.    /* Was there a death here?  If so, remove dying piece */
  1035.    if (ChessBoard.mx2.my2 ~= Piece.BLANK) then do
  1036.        VictimPiece = GetPiecePos(mx2, my2)
  1037.     if (VictimPiece > 0) then do
  1038.         PiecePosX.1.VictimPiece = 9999
  1039.         PiecePosY.1.VictimPiece = 9999
  1040.         end
  1041.     else do
  1042.         VictimPiece = abs(VictimPiece)
  1043.         PiecePosX.2.VictimPiece = 9999
  1044.         PiecePosY.2.VictimPiece = 9999
  1045.         end
  1046.     end
  1047.     
  1048.    /* See if there was a pawn promotion on this move */
  1049.    if (promcode > 1) then do
  1050.        /* Get side code */
  1051.     if (ChessBoard.mx1.my1 > 0) then do
  1052.         tSide = 1
  1053.         end
  1054.     else do
  1055.         tSide = -1
  1056.         end
  1057.        if (promcode == 2) then ChessBoard.mx1.my1 = Piece.KNIGHT * tSide
  1058.        if (promcode == 3) then ChessBoard.mx1.my1 = Piece.QUEEN  * tSide
  1059.        if (promcode == 4) then ChessBoard.mx1.my1 = Piece.ROOK   * tSide
  1060.        if (promcode == 5) then ChessBoard.mx1.my1 = Piece.BISHOP * tSide
  1061.        say "promotion to "promcode
  1062.        end
  1063.        
  1064.    ChessBoard.mx2.my2 = ChessBoard.mx1.my1  /* Then put the piece in the new spot! */
  1065.    ChessBoard.mx1.my1 = Piece.BLANK
  1066.    
  1067.    return checkcode
  1068.    
  1069.  
  1070.  
  1071.  
  1072. /* --------------------------------------------------------------- */
  1073. /* procedure UpdateStatus                                             */
  1074. /* --------------------------------------------------------------- */
  1075. UpdateStatus: procedure expose GlobData. ACTIVE PASSIVE
  1076.     
  1077.     /* Say whose turn it is */
  1078.     if (GlobData.turn ~= GlobData.BActive) then LocalOrRemote = "It's Their turn" 
  1079.     if ((GlobData.BConnectMode == 0)|(GlobData.turn == GlobData.BActive)) then LocalOrRemote = "It's Your turn"
  1080.  
  1081.     if (GlobData.turn == ACTIVE) then do
  1082.         LocalOrRemote = '"' || LocalOrRemote || " (White)" || '"'
  1083.         end
  1084.         else do
  1085.         LocalOrRemote = '"' || LocalOrRemote || " (Black)" || '"'
  1086.         end
  1087.             
  1088.     SetWindowTitle LocalOrRemote
  1089.     return 1
  1090.     
  1091.  
  1092.  
  1093. /* --------------------------------------------------------------- */
  1094. /* procedure DrawPiece                                              */
  1095. /* --------------------------------------------------------------- */
  1096. DrawPiece: procedure expose GlobData. piece.
  1097.     parse arg X, Y, PieceCode, BFlood
  1098.     
  1099.     /* Decode PieceCode */
  1100.     PieceColor = GlobData.SIDE1PEN
  1101.     
  1102.     if (PieceCode < 0) then do
  1103.         PieceCode = abs(PieceCode)
  1104.         PieceColor = GlobData.SIDE2PEN
  1105.         end
  1106.     
  1107.     /* Get co-ords of our square */
  1108.     xleft   = trunc(GlobData.BoardWidth / 8) * X
  1109.     ytop    = (trunc(GlobData.BoardHeight / 8) * Y) + GlobData.ToolBarHeight
  1110.     xd      = trunc(GlobData.BoardWidth / 8) - 1
  1111.     yd      = trunc(GlobData.BoardHeight/ 8) - 1
  1112.     xright  = xleft + xd
  1113.     ybottom = ytop + yd
  1114.     xcenter = (xleft + trunc(xd/2)) 
  1115.     ycenter = (ytop + trunc(yd/2)) 
  1116.     
  1117.     /* First thing we need to do is erase the square */
  1118.     sqc = SquareColor(X, Y)
  1119.     setfpen sqc
  1120.     square xleft ytop xright ybottom fill
  1121.  
  1122.     /* If we're doing a filled mode draw, then outline in the other team's color */
  1123.     if (BFlood > 0) then do
  1124.             if (PieceColor == GlobData.SIDE1PEN) then do
  1125.                 OutlineColor = GlobData.SIDE2PEN
  1126.                 end 
  1127.             else do
  1128.                 OutlineColor = GlobData.SIDE1PEN
  1129.                 end
  1130.             end
  1131.             else do
  1132.                 OutlineColor = PieceColor
  1133.             end             
  1134.  
  1135.     /* Set color to appropriate side */
  1136.     setfpen OutlineColor
  1137.         
  1138.     if (PieceCode == piece.PAWN) then do
  1139.         penreset
  1140.         pen (xleft+trunc(xd*.56))  (ytop+trunc(yd*.47))
  1141.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.8)) 
  1142.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.9)) 
  1143.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.9)) 
  1144.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.8)) 
  1145.         pen (xleft+trunc(xd*.44))  (ytop+trunc(yd*.47))
  1146.         if BFlood > 0 then do
  1147.                 setfpen PieceColor
  1148.                 circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.38)) (trunc(xd*.16)) (trunc(yd*.16)) fill
  1149.                     setfpen OutlineColor
  1150.                     end
  1151.         circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.38)) (trunc(xd*.16)) (trunc(yd*.16))
  1152.  
  1153.             if BFlood > 0 then do
  1154.                 setfpen PieceColor
  1155.                     flood xcenter (ytop + trunc(yd * .8))
  1156.                     end
  1157.     end
  1158.     else if (PieceCode == piece.ROOK) then do
  1159.         penreset
  1160.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.2))
  1161.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.2))
  1162.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.3))
  1163.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.3))
  1164.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.2))
  1165.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.2))
  1166.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.3))
  1167.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.3))
  1168.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.2))
  1169.         pen (xleft+trunc(xd*.7))   (ytop+trunc(yd*.2))
  1170.         pen (xleft+trunc(xd*.7))   (ytop+trunc(yd*.3))
  1171.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.4))
  1172.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.7))
  1173.         pen (xleft+trunc(xd*.75))  (ytop+trunc(yd*.9))
  1174.         pen (xleft+trunc(xd*.25))  (ytop+trunc(yd*.9))
  1175.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.7))
  1176.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.4))
  1177.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.3))
  1178.         pen (xleft+trunc(xd*.3))   (ytop+trunc(yd*.2))
  1179.             setfpen PieceColor
  1180.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop + trunc(yd*.5))
  1181.     end 
  1182.     else if (PieceCode == piece.KNIGHT) then do
  1183.         penreset 
  1184.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.2))
  1185.             pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.10))
  1186.             pen (xleft+trunc(xd*.33)) (ytop+trunc(yd*.19))
  1187.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.2))
  1188.         pen (xleft+trunc(xd*.7))  (ytop+trunc(yd*.4))
  1189.         pen (xleft+trunc(xd*.65)) (ytop+trunc(yd*.45))
  1190.         pen (xleft+trunc(xd*.5))  (ytop+trunc(yd*.4))
  1191.         pen (xleft+trunc(xd*.5))  (ytop+trunc(yd*.5))
  1192.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.6))
  1193.         pen (xleft+trunc(xd*.75)) (ytop+trunc(yd*.9))
  1194.         pen (xleft+trunc(xd*.25)) (ytop+trunc(yd*.9))
  1195.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.8))
  1196.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.7))
  1197.         pen (xleft+trunc(xd*.2))  (ytop+trunc(yd*.4))
  1198.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.2))
  1199.             setfpen PieceColor
  1200.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.75))
  1201.         setfpen OutlineColor
  1202.         circle (xleft+trunc(xd*.55)) (ytop+trunc(yd*.3)) trunc(xd/20) trunc(yd/20) fill
  1203.     end
  1204.     else if (PieceCode == piece.BISHOP) then do
  1205.         penreset
  1206.         pen (xleft+trunc(xd*.48))  (ytop+trunc(yd*.2))
  1207.         pen (xleft+trunc(xd*.4))   (ytop+trunc(yd*.3))
  1208.         pen (xleft+trunc(xd*.45))  (ytop+trunc(yd*.4))
  1209.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.7))
  1210.         pen (xleft+trunc(xd*.35))  (ytop+trunc(yd*.9))
  1211.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.9))
  1212.         pen (xleft+trunc(xd*.65))  (ytop+trunc(yd*.7))
  1213.         pen (xleft+trunc(xd*.55))  (ytop+trunc(yd*.4))
  1214.         pen (xleft+trunc(xd*.6))   (ytop+trunc(yd*.3))
  1215.         pen (xleft+trunc(xd*.52))  (ytop+trunc(yd*.2))
  1216.         if BFlood > 0 then do
  1217.             setfpen PieceColor
  1218.             circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.2)) trunc(xd*.08) trunc(yd*.08) fill
  1219.             setfpen OutlineColor
  1220.             end
  1221.         circle (xleft+trunc(xd*.5)) (ytop+trunc(yd*.2)) trunc(xd*.08) trunc(yd*.08)
  1222.             if BFlood > 0 then do
  1223.                 setfpen PieceColor
  1224.                flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.8))
  1225.                 end
  1226.     end
  1227.     else if (PieceCode == piece.QUEEN) then do
  1228.         penreset
  1229.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.1))
  1230.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.1))
  1231.         pen (xleft+trunc(xd*.7)) (ytop+trunc(yd*.15))
  1232.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.3))
  1233.         pen (xleft+trunc(xd*.6)) (ytop+trunc(yd*.7))
  1234.         pen (xleft+trunc(xd*.8)) (ytop+trunc(yd*.9))
  1235.         pen (xleft+trunc(xd*.2)) (ytop+trunc(yd*.9))
  1236.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.7))
  1237.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.3))
  1238.         pen (xleft+trunc(xd*.3)) (ytop+trunc(yd*.15))
  1239.         pen (xleft+trunc(xd*.4)) (ytop+trunc(yd*.1))
  1240.             setfpen PieceColor
  1241.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop + trunc(yd*.75))
  1242.     end
  1243.     else if (PieceCode == piece.KING) then do
  1244.         penreset
  1245.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.1))
  1246.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.1))
  1247.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.2))
  1248.         pen (xleft+trunc(xd*.57)) (ytop+trunc(yd*.2))
  1249.         pen (xleft+trunc(xd*.57)) (ytop+trunc(yd*.3))
  1250.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.3))
  1251.         pen (xleft+trunc(xd*.53)) (ytop+trunc(yd*.4))
  1252.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.5))
  1253.         pen (xleft+trunc(xd*.55)) (ytop+trunc(yd*.6))
  1254.         pen (xleft+trunc(xd*.6))  (ytop+trunc(yd*.8))
  1255.         pen (xleft+trunc(xd*.7))  (ytop+trunc(yd*.9))
  1256.         pen (xleft+trunc(xd*.3))  (ytop+trunc(yd*.9))
  1257.         pen (xleft+trunc(xd*.4))  (ytop+trunc(yd*.8))
  1258.         pen (xleft+trunc(xd*.45)) (ytop+trunc(yd*.6))
  1259.         pen (xleft+trunc(xd*.4))  (ytop+trunc(yd*.5))
  1260.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.4))
  1261.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.3))
  1262.         pen (xleft+trunc(xd*.43)) (ytop+trunc(yd*.3))
  1263.         pen (xleft+trunc(xd*.43)) (ytop+trunc(yd*.2))
  1264.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.2))
  1265.         pen (xleft+trunc(xd*.47)) (ytop+trunc(yd*.1))
  1266.             setfpen PieceColor
  1267.         if BFlood > 0 then flood (xleft+trunc(xd*.5)) (ytop+trunc(yd*.7))
  1268.     end
  1269.     return 1